home *** CD-ROM | disk | FTP | other *** search
/ MacHack 1998 / MacHack 1998.toast / The Hacks! / MemBuddy / SillyBalls.c < prev    next >
C/C++ Source or Header  |  1998-05-16  |  16KB  |  658 lines

  1. // ******************************************************************
  2. //    program written by 
  3. //                         Paul Baxter
  4. //                         MacHack'98
  5. //
  6. // ******************************************************************
  7.  
  8. #include <A4Stuff.h>
  9. #include <LowMem.h>
  10. #include "membuddy.h"
  11.  
  12. #define SYS                0x0500    // sys trap attribute
  13.  
  14. #define eHandleQueType    'HQ'    // que types
  15. #define ePtrQueType        'PQ'
  16.  
  17. typedef struct {
  18.     struct QElem *qLink;        // next element
  19.     short qType;                // always kHandleQueType
  20.     ProcessSerialNumber process;// process number
  21.     Handle    theHandle;            // Handle
  22. } HandleQElem;
  23. typedef HandleQElem* HandleQElemPtr;
  24.  
  25. typedef struct {
  26.     struct QElem*        qLink;    // next element
  27.     short                qType;    // always kHandleQueType
  28.     ProcessSerialNumber process;// process number
  29.     Ptr                    thePtr;    // Pointer
  30. } PtrQElem;
  31. typedef PtrQElem* PtrQElemPtr;
  32.  
  33. asm void MyNewHandle(void);        // the patches
  34. asm void MyNewHandleClear(void);
  35. asm void MyNewPtr(void);
  36. asm void MyNewPtrClear(void);
  37. asm void MyDisposeHandle(void);
  38. asm void MyDisposePtr(void);
  39.  
  40.                                 // utility functions
  41. void AddHandletoQue(Handle theHandle : __A0);
  42. void RemoveHandleFromQue(Handle theHandle: __A0);
  43. void AddPtrtoQue(Ptr thePtr : __A0);
  44. void RemovePointerFromQue(Ptr thePtr: __A0);
  45. void FreeProcMem(void);
  46.  
  47. typedef struct {                // typedef ques for storing handles and ptrs
  48.     QHdr HandleQue;
  49.     QHdr PointerQue;
  50. } Ques;
  51.  
  52.  
  53. Ptr    gOldNewHandle = nil;        // old and new trap addresses
  54. Ptr    gMyNewHandle = nil;
  55. Ptr gOldNewHandleClear = nil;
  56. Ptr gMyNewHandleClear = nil;
  57. Ptr gOldDisposeHandle = nil;
  58. Ptr gMyDisposeHandle = nil;
  59. Ptr gOldDisposePtr = nil;
  60. Ptr gMyDisposePtr = nil;
  61. Ptr    gOldNewPtr = nil;
  62. Ptr    gMyNewPtr = nil;
  63. Ptr gOldNewPtrClear = nil;
  64. Ptr gMyNewPtrClear = nil;
  65.  
  66. long gNumHandles = 0;            // num handles we allocated
  67. long gNumPtrs = 0;                // num pointers we allocated
  68.  
  69.  
  70. Ques gMyQues;                    // the que header
  71.                                 // flag for internal calls
  72. Boolean gInternalDispose = false;
  73. // ******************************************************************
  74. //
  75. //        Main
  76. //                main entry point
  77. //
  78. // ******************************************************************
  79. void main(void)
  80. {
  81.     Handle myhandle;
  82.  
  83.     EnterCodeResource();        // get globals
  84.  
  85.                                 // init pointer que
  86.     gMyQues.PointerQue.qFlags = 0;
  87.     gMyQues.PointerQue.qHead = nil;
  88.     gMyQues.PointerQue.qTail = nil;
  89.                                 // init handle que
  90.     gMyQues.HandleQue.qFlags = 0;
  91.     gMyQues.HandleQue.qHead = nil;
  92.     gMyQues.HandleQue.qTail = nil;
  93.  
  94.                                 // detach ourselves
  95.     myhandle = Get1Resource('INIT', 0);
  96.     if (myhandle) {
  97.         HLock(myhandle);
  98.         DetachResource(myhandle);
  99.                                 // install patches
  100.         SetTrap(NewHandle);
  101.         SetTrap(NewHandleClear);
  102.         SetTrap(DisposeHandle);
  103.         SetTrap(NewPtr);
  104.         SetTrap(NewPtrClear);
  105.         SetTrap(DisposePtr);
  106.     }
  107.  
  108.     ExitCodeResource();
  109. }
  110.  
  111.  
  112. // ******************************************************************
  113. //
  114. //        MyNewHandle
  115. //                NewHandle patch
  116. //
  117. // ******************************************************************
  118. asm void MyNewHandle(void)
  119. {
  120.     Handle newhand;                // newly allocated handle
  121.     long size;                    // allocation size
  122.     long oldA4;                    // globals ptr
  123.     short trapword;                // trap used
  124.  
  125.     fralloc                        // set stack frame
  126.  
  127.     movem.l    D0-D2/A0-A3,-(SP)    // save regs
  128.     jsr        FreeProcMem
  129.     movem.l    (SP)+,D0-D2/A0-A3    // restore regs
  130.  
  131.     movem.l    D1/A1-A3,-(SP)        // save regs
  132.  
  133.     move.l    D0,size                // save size
  134.     move.w    D1,trapword            // save trap word
  135.  
  136.     jsr       SetCurrentA4        // set up
  137.     move.l    D0, oldA4            // globals
  138.     move.l    size, D0            // fix D0 (size)
  139.  
  140.     movea.l    gOldNewHandle,A1    // get old trap address
  141.     jsr        (A1)                // call old routine
  142.     tst.w    D0                    // check for error
  143.     beq.s    @done                // noErr  just exit
  144.  
  145.     move.w    trapword,D1            // get trap word
  146.     cmp.w    _NewHandleClear,D1    // _NewHandle = A122
  147.                                 // _NewHandleClear = A322
  148.                                 // _NewHandleSys = A522
  149.                                 // _NewHandleSysClear = A722
  150.     bgt.s    @done                // if system heap don't try again
  151.  
  152.     move.l    size,D0                // restore requested size
  153.     ori.l    #SYS,D1                // set system bit
  154.     movea.l    gOldNewHandle,A1    // get old trap address
  155.     jsr        (A1)                // call old routine
  156.  
  157.     tst.w    D0                    // check result
  158.     bne        @done
  159.  
  160.     move.l    A0,newhand            // save handle
  161.     jsr        AddHandletoQue        // add it to our que
  162.     move.l    newhand,A0            // restore result
  163.     clr.w    D0                    // we already know there is no error
  164.  
  165. @done:
  166.     movea.l    oldA4,A4            // restore A4
  167.     movem.l    (SP)+,D1/A1-A3        // restore regs
  168.     frfree                        // unlink stack frame
  169.     tst.w    D0                    // undocumented test for error
  170.  
  171.     rts
  172. }
  173.  
  174. // ******************************************************************
  175. //
  176. //        MyNewHandleClear
  177. //                MyNewHandleClear patch
  178. //
  179. // ******************************************************************
  180. asm void MyNewHandleClear(void)
  181. {
  182.     Handle newhand;                // newly allocated handle
  183.     long size;                    // allocation size
  184.     long oldA4;                    // globals ptr
  185.     short trapword;                // trap used
  186.  
  187.     fralloc                        // set stack frame
  188.  
  189.     movem.l    D0-D2/A0-A3,-(SP)    // save regs
  190.     jsr        FreeProcMem
  191.     movem.l    (SP)+,D0-D2/A0-A3    // restore regs
  192.  
  193.     movem.l    D1/A1-A3,-(SP)        // save regs
  194.  
  195.     move.l    D0,size                // save size
  196.     move.w    D1,trapword            // save trap word
  197.  
  198.     jsr       SetCurrentA4        // set up
  199.     move.l    D0, oldA4            // globals
  200.     move.l    size, D0            // fix D0 (size)
  201.  
  202.                                 // get old trap address
  203.     movea.l    gOldNewHandleClear,A1
  204.     jsr        (A1)                // call old routine
  205.     tst.w    D0                    // check for error
  206.     beq.s    @done                // noErr  just exit
  207.  
  208.     move.w    trapword,D1            // get trap word
  209.     cmp.w    _NewHandleClear,D1    // _NewHandle = A122
  210.                                 // _NewHandleClear = A322
  211.                                 // _NewHandleSys = A522
  212.                                 // _NewHandleSysClear = A722
  213.     bgt.s    @done                // if system heap don't try again
  214.  
  215.     move.l    size,D0                // restore requested size
  216.     _NewHandleSysClear            // try system heap
  217.  
  218.     tst.w    D0                    // check result
  219.     bne        @done
  220.  
  221.     move.l    A0,newhand            // save handle
  222.     jsr        AddHandletoQue        // add it to our que
  223.     move.l    newhand,A0            // restore result
  224.     clr.w    D0                    // we already know there is no error
  225.  
  226. @done:
  227.     movea.l    oldA4,A4            // restore A4
  228.     movem.l    (SP)+,D1/A1-A3        // restore regs
  229.     frfree                        // unlink stack frame
  230.     tst.w    D0                    // undocumented test for error
  231.  
  232.     rts
  233. }
  234.  
  235. // ******************************************************************
  236. //
  237. //        MyNewPtr
  238. //                NewPtr patch
  239. //
  240. // ******************************************************************
  241. asm void MyNewPtr(void)
  242. {
  243.     long size;                    // allocation size
  244.     long oldA4;                    // globals ptr
  245.     short trapword;                // trap used
  246.     Ptr     thePtr;                // pointer allocated
  247.  
  248.     fralloc                        // set stack frame
  249.  
  250.     movem.l    D0-D2/A0-A3,-(SP)    // save regs
  251.     jsr        FreeProcMem
  252.     movem.l    (SP)+,D0-D2/A0-A3    // restore regs
  253.  
  254.     move.l    D0,size                // save size
  255.     move.w    D1,trapword            // save trap word
  256.  
  257.     movem.l    D1/A1-A3,-(SP)        // save regs
  258.  
  259.     jsr       SetCurrentA4        // set up
  260.     move.l    D0, oldA4            // globals
  261.     move.l    size,D0                // fix D0 (size)
  262.  
  263.     movea.l    gOldNewPtr,A1        // get old trap address
  264.     jsr        (A1)                // call old routine
  265.     tst.w    D0                    // check for error
  266.     beq.s    @done                // noErr  just exit
  267.  
  268.     move.w    trapword,D1            // get trap word
  269.     cmp.w    #_NewPtrClear,D1    // _NewPtr = A11E
  270.                                 // _NewPtrClear = A31E
  271.                                 // _NewPtrSys = A51E
  272.                                 // _NewPtrSysClear = A71E
  273.     
  274.     bgt.s    @done                // if system heap don't try again
  275.  
  276.     move.l    size,D0                // restore requested size
  277.     ori.l    #SYS,D1                // set system bit
  278.     movea.l    gOldNewPtr,A1        // get old trap address
  279.     jsr        (A1)                // call old routine
  280.  
  281.     tst.w    D0                    // check result
  282.     bne        @done
  283.  
  284.     move.l    A0,thePtr            // save Pointer
  285.     jsr        AddPtrtoQue            // add it to our que
  286.     move.l    thePtr,A0            // restore result
  287.     clr.w    D0                    // we already know there is no error
  288.  
  289. @done:
  290.     movea.l    oldA4,A4            // restore A4
  291.  
  292.     movem.l    (SP)+,D1/A1-A3        // restore regs
  293.  
  294.     frfree                        // unlink stack frame
  295.     tst.w    D0
  296.  
  297.     rts
  298. }
  299.  
  300. // ******************************************************************
  301. //
  302. //        MyNewPtrClear
  303. //                MyNewPtrClear patch
  304. //
  305. // ******************************************************************
  306. asm void MyNewPtrClear(void)
  307. {
  308.     long size;                    // allocation size
  309.     long oldA4;                    // globals ptr
  310.     short trapword;                // trap used
  311.     Ptr     thePtr;                // pointer allocated
  312.  
  313.     fralloc                        // set stack frame
  314.  
  315.     movem.l    D0-D2/A0-A3,-(SP)    // save regs
  316.     jsr        FreeProcMem
  317.     movem.l    (SP)+,D0-D2/A0-A3    // restore regs
  318.  
  319.     move.l    D0,size                // save size
  320.     move.w    D1,trapword            // save trap word
  321.  
  322.     movem.l    D1/A1-A3,-(SP)        // save regs
  323.  
  324.     jsr       SetCurrentA4        // set up
  325.     move.l    D0, oldA4            // globals
  326.     move.l    size,D0                // fix D0 (size)
  327.  
  328.     movea.l    gOldNewPtr,A1        // get old trap address
  329.     jsr        (A1)                // call old routine
  330.     tst.w    D0                    // check for error
  331.     beq.s    @done                // noErr  just exit
  332.  
  333.     move.w    trapword,D1            // get trap word
  334.     cmp.w    #_NewPtrClear,D1    // _NewPtr = A11E
  335.                                 // _NewPtrClear = A31E
  336.                                 // _NewPtrSys = A51E
  337.                                 // _NewPtrSysClear = A71E
  338.     
  339.     bgt.s    @done                // if system heap don't try again
  340.  
  341.     move.l    size,D0                // restore requested size
  342.     _NewPtrSysClear                // try system heap
  343.  
  344.     tst.w    D0                    // check result
  345.     bne        @done
  346.  
  347.     move.l    A0,thePtr            // save Pointer
  348.     jsr        AddPtrtoQue            // add it to our que
  349.     move.l    thePtr,A0            // restore result
  350.     clr.w    D0                    // we already know there is no error
  351.  
  352. @done:
  353.     movea.l    oldA4,A4            // restore A4
  354.  
  355.     movem.l    (SP)+,D1/A1-A3        // restore regs
  356.  
  357.     frfree                        // unlink stack frame
  358.     tst.w    D0
  359.  
  360.     rts
  361. }
  362.  
  363. // ******************************************************************
  364. //
  365. //        MyDisposeHandle
  366. //                MyDisposeHandle patch
  367. //
  368. // ******************************************************************
  369. asm void MyDisposeHandle(void)
  370. {
  371.     long oldA4;
  372.     long theHandle;
  373.     short trapword;
  374.  
  375.     fralloc                        // set stack frame
  376.  
  377.     move.l    A0,theHandle        // save handle
  378.     move.w    D1,trapword            // save trap word
  379.  
  380.     movem.l    D0-D2/A0-A3,-(SP)    // save regs
  381.     jsr        RemoveHandleFromQue
  382.     movem.l    (SP)+,D0-D2/A0-A3    // restore regs
  383.  
  384.     movem.l    D1/A1,-(SP)            // save regs
  385.  
  386.     jsr       SetCurrentA4        // set up globals
  387.     move.l    D0,oldA4
  388.  
  389.     move.w    trapword,D1            // reset trap
  390.     move.l    theHandle,A0        // reset handle                
  391.     movea.l    gOldDisposeHandle,A1// get old trap address
  392.  
  393.     jsr        (A1)                // call old routine
  394.     movea.l    oldA4,A4            // restore A4
  395.  
  396.     movem.l    (SP)+,D1/A1            // restore regs
  397.  
  398.     move.l    #0,A0
  399.  
  400.     frfree                        // unlink stack frame
  401.     rts
  402.  
  403. }
  404.  
  405. // ******************************************************************
  406. //
  407. //        MyDisposePtr
  408. //                MyDisposePtr patch
  409. //
  410. // ******************************************************************
  411. asm void MyDisposePtr(void)
  412. {
  413.     long oldA4;
  414.     long thePtr;
  415.     short trapword;
  416.  
  417.     fralloc                        // set stack frame
  418.  
  419.     move.l    A0,thePtr
  420.     move.w    D1,trapword            // save trap word
  421.  
  422.  
  423.     movem.l    D0-D2/A0-A3,-(SP)    // save regs
  424.     jsr        RemovePointerFromQue
  425.     movem.l    (SP)+,D0-D2/A0-A3    // restore regs
  426.  
  427.     movem.l    D1/A1,-(SP)            // save regs
  428.  
  429.     jsr       SetCurrentA4        // set up globals
  430.     move.l    D0,oldA4
  431.                                 // get old trap address
  432.     move.w    trapword,D1
  433.     move.l    thePtr,A0                        
  434.     move.l    gOldDisposePtr,A1    
  435.  
  436.     jsr        (A1)                // call old routine
  437.     movea.l    oldA4,A4            // restore A4
  438.  
  439.     movem.l    (SP)+,D1/A1            // restore regs
  440.  
  441.     frfree                        // unlink stack frame
  442.     move.l    #0,A0
  443.  
  444.     rts
  445.  
  446. }
  447.  
  448. // ******************************************************************
  449. //
  450. //        AddHandletoQue
  451. //                Add a handle to our handle que
  452. //
  453. // ******************************************************************
  454. void AddHandletoQue(Handle theHandle : __A0)
  455. {
  456.     HandleQElemPtr    handleQuePtr;
  457.     ProcessSerialNumber    proc;
  458.     OSErr err;
  459.  
  460.     err = GetCurrentProcess(&proc);
  461.     if (!err) {
  462.         handleQuePtr = (HandleQElemPtr)NewPtrSys(sizeof(HandleQElem));
  463.         handleQuePtr->qLink = 0;
  464.         handleQuePtr->qType = eHandleQueType;
  465.  
  466.         handleQuePtr->theHandle = theHandle;
  467.         BlockMoveData(&proc, &handleQuePtr->process, sizeof(ProcessSerialNumber));
  468.         Enqueue((QElem *) handleQuePtr, &gMyQues.HandleQue);
  469.         gNumHandles++;
  470.     }
  471. }
  472.  
  473.  
  474. // ******************************************************************
  475. //
  476. //        AddPtrtoQue
  477. //                Add a pointer to our pointer que
  478. //
  479. // ******************************************************************
  480. void AddPtrtoQue(Ptr thePtr : __A0)
  481. {
  482.     PtrQElemPtr    ptrQuePtr;
  483.     ProcessSerialNumber    proc;
  484.     OSErr err;
  485.  
  486.     err = GetCurrentProcess(&proc);
  487.     if (!err) {
  488.         ptrQuePtr = (PtrQElemPtr)NewPtrSys(sizeof(PtrQElem));
  489.         ptrQuePtr->qLink = 0;
  490.         ptrQuePtr->qType = ePtrQueType;
  491.  
  492.         ptrQuePtr->thePtr = thePtr;
  493.         BlockMoveData(&proc, &ptrQuePtr->process, sizeof(ProcessSerialNumber));
  494.         Enqueue((QElem *) ptrQuePtr, &gMyQues.PointerQue);
  495.  
  496.         gNumPtrs++;
  497.     }
  498. }
  499.  
  500.  
  501. // ******************************************************************
  502. //
  503. //        FreeProcMem
  504. //                free memmory if appropriate
  505. //
  506. // ******************************************************************
  507. void FreeProcMem(void)
  508. {
  509.     ProcessInfoRec procInfo;
  510.     Str255 name;
  511.     FSSpec appSpec;
  512.     HandleQElemPtr handleQuePtr;
  513.     PtrQElemPtr ptrQuePtr;
  514.     unsigned long size;
  515.     OSErr err;
  516.     short resflags;
  517.     Boolean found;
  518.  
  519.     EnterCodeResource();
  520.     gInternalDispose = true;
  521.  
  522.     if ((gNumHandles > 0 || gNumPtrs > 0)) {
  523.  
  524.  
  525.         // kill handles
  526.         do {
  527.             found = true;
  528.             handleQuePtr = (HandleQElemPtr) gMyQues.HandleQue.qHead;
  529.             while (handleQuePtr) {
  530.  
  531.                 procInfo.processInfoLength = sizeof(ProcessInfoRec);
  532.                 procInfo.processName = name;
  533.                 procInfo.processAppSpec = &appSpec;
  534.                 
  535.                 err = GetProcessInformation(&handleQuePtr->process,&procInfo);
  536.                 found = (err == noErr);
  537.                 // see if the process is still running
  538.                 if (!found) {
  539.                     // check resource attribute
  540.                     resflags = GetResAttrs(handleQuePtr->theHandle);
  541.                     if (ResError()) {
  542.                         size = GetHandleSize(handleQuePtr->theHandle);
  543.                         if (size) {
  544.                             HUnlock(handleQuePtr->theHandle);
  545.                             HPurge(handleQuePtr->theHandle);
  546.                             DisposeHandle(handleQuePtr->theHandle);
  547.                         }
  548.                     }
  549.                     Dequeue((QElem *)handleQuePtr, &gMyQues.HandleQue);
  550.                     gNumHandles--;
  551.                     DisposePtr((Ptr)handleQuePtr);
  552.                     // DO NOT ZERO OUT  handleQuePtr
  553.                     break;
  554.                 }
  555.                 handleQuePtr = (HandleQElemPtr) handleQuePtr->qLink;
  556.             }
  557.         } while (!found);    
  558.  
  559.  
  560.         // Kill Pointers
  561.         do {
  562.             found = true;
  563.             ptrQuePtr = (PtrQElemPtr) gMyQues.PointerQue.qHead;
  564.             while (ptrQuePtr) {
  565.  
  566.                 procInfo.processInfoLength = sizeof(ProcessInfoRec);
  567.                 procInfo.processName = name;
  568.                 procInfo.processAppSpec = &appSpec;
  569.  
  570.                 err = GetProcessInformation(&ptrQuePtr->process, &procInfo);
  571.                 found = (err == noErr);
  572.                 // see if the process is still running
  573.                 if (!found) {
  574.                     size = GetPtrSize(ptrQuePtr->thePtr);
  575.                     if (size) {
  576.                         DisposePtr(ptrQuePtr->thePtr);
  577.                     }
  578.                     Dequeue((QElem *)ptrQuePtr, &gMyQues.PointerQue);
  579.                     gNumPtrs--;
  580.                     DisposePtr((Ptr)ptrQuePtr);
  581.                     // DO NOT ZERO OUT  ptrQuePtr
  582.                     break;
  583.                 }
  584.                 ptrQuePtr = (PtrQElemPtr) ptrQuePtr->qLink;
  585.             }
  586.         } while (!found);    
  587.  
  588.     }
  589.  
  590.     gInternalDispose = false;
  591.  
  592.     ExitCodeResource();
  593. }
  594.  
  595. // ******************************************************************
  596. //
  597. //        RemovePointerFromQue
  598. //                remove a pointer from the pointer que
  599. //
  600. // ******************************************************************
  601. void RemovePointerFromQue(Ptr thePointer: __A0)
  602. {
  603.     PtrQElemPtr ptrQuePtr;
  604.  
  605.     EnterCodeResource();
  606.  
  607.     if (gInternalDispose) {
  608.         ExitCodeResource();
  609.         return;
  610.     }
  611.  
  612.     ptrQuePtr = (PtrQElemPtr) gMyQues.PointerQue.qHead;
  613.     while (ptrQuePtr) {
  614.         if (ptrQuePtr->thePtr == thePointer) {
  615.             Dequeue((QElem *)ptrQuePtr, &gMyQues.PointerQue);
  616.             gNumPtrs --;
  617.             DisposePtr((Ptr)ptrQuePtr);
  618.             break;
  619.         }
  620.         ptrQuePtr = (PtrQElemPtr) ptrQuePtr->qLink;
  621.     }
  622.  
  623.     ExitCodeResource();
  624.     FreeProcMem();
  625. }
  626.  
  627. // ******************************************************************
  628. //
  629. //        RemoveHandleFromQue
  630. //                remove a handle from the handle que
  631. //
  632. // ******************************************************************
  633. void RemoveHandleFromQue(Handle theHandle: __A0)
  634. {
  635.     HandleQElemPtr handleQuePtr;
  636.  
  637.     EnterCodeResource();
  638.  
  639.     if (gInternalDispose) {
  640.         ExitCodeResource();
  641.         return;
  642.     }
  643.     
  644.     handleQuePtr = (HandleQElemPtr) gMyQues.HandleQue.qHead;
  645.     while (handleQuePtr) {
  646.         if (handleQuePtr->theHandle == theHandle) {
  647.             Dequeue((QElem *)handleQuePtr, &gMyQues.HandleQue);
  648.             gNumHandles--;
  649.             DisposePtr((Ptr)handleQuePtr);
  650.             break;
  651.         }
  652.         handleQuePtr = (HandleQElemPtr) handleQuePtr->qLink;
  653.     }
  654.     ExitCodeResource();
  655.  
  656.     FreeProcMem();
  657.  
  658. }